package cn.mujiankeji.mbrowser.界面.框架.主视图

import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.gestures.detectDragGestures
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.RowScope
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.MoreVert
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.LinearProgressIndicator
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import cn.mujiankeji.mbrowser.工具.clickable2
import cn.mujiankeji.mbrowser.数据.枚举类.功能枚举
import cn.mujiankeji.mbrowser.数据.配置项.应用配置
import cn.mujiankeji.mbrowser.界面.图标.MyIconPack
import cn.mujiankeji.mbrowser.界面.图标.myiconpack.主页
import cn.mujiankeji.mbrowser.界面.图标.myiconpack.刷新
import cn.mujiankeji.mbrowser.界面.图标.myiconpack.前进
import cn.mujiankeji.mbrowser.界面.图标.myiconpack.后退
import cn.mujiankeji.mbrowser.界面.图标.myiconpack.菜单
import cn.mujiankeji.mbrowser.界面.小窗页.详情输入小窗页面状态
import cn.mujiankeji.mbrowser.app.界面模块
import org.koin.compose.koinInject
import 界面.app.图标.myiconpack.未选中
import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.animation.core.tween
import androidx.compose.animation.core.RepeatMode
import androidx.compose.animation.core.infiniteRepeatable
import androidx.compose.animation.core.LinearEasing
import androidx.compose.animation.core.FastOutSlowInEasing
import androidx.compose.animation.core.animateFloat
import androidx.compose.animation.core.rememberInfiniteTransition
import kotlinx.coroutines.delay
import kotlin.math.abs
import androidx.compose.ui.geometry.Offset


@Composable
fun 顶部工具栏(){
    // 暂不实现
}



class 工具栏状态(val viewState : 界面模块){
    var 背景颜色 by mutableStateOf(Color.White)
    var 内容颜色 by mutableStateOf(Color.Black)
    var 内容停用色 by mutableStateOf(Color.Gray) // 如按钮不可用
    var 背景次色 by mutableStateOf(Color(0XFFF3F3F3))

    fun 显示输入窗口(){
        详情输入小窗页面状态().显示()
    }

    fun 前进(){
        viewState.前进()
    }
    fun 后退(){
        viewState.后退()
    }
    fun 刷新(){
        viewState.刷新()
    }
}



@Composable
fun 底部进度条(界面模块: 界面模块 = koinInject()){
    // 动态进度条效果，使其看起来始终在动态加载
    Box(Modifier
        .height(2.dp)
        .fillMaxWidth()){
        if (界面模块.进度 in 1..99) {
            // 记住上一次真实进度
            var 上一次进度 by remember { mutableStateOf(0f) }
            // 当前显示进度（动画值）
            var 当前显示进度 by remember { mutableStateOf(0f) }
            // 目标进度（真实进度）
            val 目标进度 = 界面模块.进度 / 100f
            // 是否需要平滑加载动画
            var 需要动画 by remember { mutableStateOf(false) }

            // 动画效果：平滑过渡到目标进度
            val 动画进度 by animateFloatAsState(
                targetValue = 当前显示进度,
                animationSpec = tween(
                    // 动画时长根据进度差距决定
                    durationMillis = if (当前显示进度 > 目标进度) 300 else 800,
                    easing = FastOutSlowInEasing
                ),
                label = "进度动画"
            )

            // 加载动画效果：当进度停滞时显示小幅度动画
            val 加载动画 = rememberInfiniteTransition(label = "加载动画")
            val 动画偏移 by 加载动画.animateFloat(
                initialValue = 0f,
                targetValue = 0.1f,
                animationSpec = infiniteRepeatable(
                    animation = tween(2000, easing = LinearEasing),
                    repeatMode = RepeatMode.Reverse
                ),
                label = "进度波动"
            )

            // 处理进度更新和动画逻辑
            LaunchedEffect(目标进度) {
                // 如果真实进度发生变化
                if (目标进度 != 上一次进度) {
                    // 如果真实进度明显增加，快速跟进
                    if (目标进度 > 当前显示进度) {
                        当前显示进度 = 目标进度
                        需要动画 = false
                    }
                    上一次进度 = 目标进度
                } else {
                    // 如果真实进度一直没变化，且在特定范围内(10%-85%)
                    if (目标进度 in 0.1f..0.85f && !需要动画) {
                        需要动画 = true
                    }
                }
            }

            // 平滑动画加载效果：当进度停滞时逐渐缓慢增加显示进度
            LaunchedEffect(需要动画, 目标进度) {
                if (需要动画 && 当前显示进度 < 0.85f) {
                    // 在目标进度前方缓慢增加，但不超过85%
                    val 最大动画进度 = minOf(目标进度 + 0.15f, 0.85f)

                    // 如果当前显示进度小于最大动画进度，缓慢增加
                    while (当前显示进度 < 最大动画进度 && 需要动画) {
                        delay(500)  // 每500ms更新一次
                        // 缓慢增加显示进度，速度随进度增加而减慢
                        当前显示进度 = minOf(当前显示进度 + 0.01f * (1f - 当前显示进度/最大动画进度), 最大动画进度)

                        // 检查真实进度是否有更新
                        if (目标进度 > 上一次进度) {
                            需要动画 = false
                            当前显示进度 = 目标进度
                            上一次进度 = 目标进度
                            break
                        }
                    }
                }
            }

            // 最终展示的进度：动画进度加上小幅度波动(当需要动画时)
            val 最终显示进度 = if (需要动画) {
                // 添加小幅度波动，但不超过85%
                minOf(动画进度 + 动画偏移 * (1f - 动画进度/0.85f), 0.85f)
            } else {
                动画进度
            }

            // 渲染进度条
            LinearProgressIndicator(
                progress = { 最终显示进度 },
                modifier = Modifier.fillMaxWidth()
            )
        }
    }
}

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun 底部导航(
    界面模块: 界面模块 = koinInject(),
    onSwipeUp: () -> Unit = {},
    onTouchStateChanged: (Boolean, Offset) -> Unit = { _, _ -> }
) {
    val state = remember { 工具栏状态(界面模块) }
    state.apply {
        背景颜色 = MaterialTheme.colorScheme.surface
        背景次色 = MaterialTheme.colorScheme.surfaceVariant
        内容停用色 = MaterialTheme.colorScheme.outline
        内容颜色 = MaterialTheme.colorScheme.onSurface
    }

    底部导航视图(state, onSwipeUp, onTouchStateChanged)
}


@Composable
private fun 底部导航视图(
    state: 工具栏状态, 
    onSwipeUp: () -> Unit,
    onTouchStateChanged: (Boolean, Offset) -> Unit
){
    val 密度 = LocalDensity.current
    val 滑动阈值 = with(密度) { 20.dp.toPx() }
    
    // 用于控制是否已经触发了滑动事件
    var 已触发滑动 by remember { mutableStateOf(false) }
    // 记录当前触摸位置
    var 当前触摸位置 by remember { mutableStateOf(Offset.Zero) }
    // 是否仍在触摸
    var 触摸中 by remember { mutableStateOf(false) }
    
    // 返回触摸状态和位置
    LaunchedEffect(触摸中, 当前触摸位置) {
        onTouchStateChanged(触摸中, 当前触摸位置)
    }
    
    Row(
        verticalAlignment = Alignment.CenterVertically,
        modifier = Modifier
            .fillMaxSize()
            .background(MaterialTheme.colorScheme.surface)
            .padding(horizontal = 4.dp)
            .pointerInput(Unit) {
                detectDragGestures(
                    onDragStart = { 起始位置 ->
                        已触发滑动 = false 
                        触摸中 = true
                        当前触摸位置 = 起始位置
                    },
                    onDragEnd = { 
                        触摸中 = false
                    },
                    onDragCancel = { 
                        触摸中 = false
                    },
                    onDrag = { change, dragAmount ->
                        change.consume()
                        
                        // 更新当前触摸位置
                        当前触摸位置 = 当前触摸位置.plus(Offset(dragAmount.x, dragAmount.y))
                        
                        // 检测向上滑动
                        if (dragAmount.y < 0 && 
                            abs(dragAmount.y) > abs(dragAmount.x) && 
                            abs(dragAmount.y) > 滑动阈值 / 5 && 
                            !已触发滑动) {
                            // 向上滑动，触发手势导航
                            onSwipeUp()
                            已触发滑动 = true
                        }
                    }
                )
            }
    ) {
        for (i in 0 until 5) {
            val 功能 = 应用配置.底部工具栏功能(i).collectAsState(initial = 功能枚举.窗口).value

            when(功能) {
                功能枚举.窗口 -> 窗口按钮视图()
                功能枚举.标题标签 -> 标题标签视图(state)
                功能枚举.后退 -> 工具栏按钮(state, MyIconPack.后退, state.viewState.可否后退) { state.后退() }
                功能枚举.前进 -> 工具栏按钮(state, MyIconPack.前进,  state.viewState.可否前进) { state.前进() }
                功能枚举.刷新 -> 工具栏按钮(state, MyIconPack.刷新, true) { state.刷新() }
                功能枚举.首页 -> 工具栏按钮(state, MyIconPack.主页,true) {
                    // TODO 跳转到主页
                }
                功能枚举.菜单 -> 工具栏按钮(state, MyIconPack.菜单,true) { state.viewState.显示菜单 = true }
                // 其他按钮...
                else -> {
                    Box(Modifier
                        .weight(1f)
                        .fillMaxHeight()
                        .clickable {})
                    {
                        Icon(
                            imageVector = Icons.Default.MoreVert,
                            contentDescription = "更多选项",
                            modifier = Modifier.align(Alignment.Center)
                        )
                    }
                }
            }
        }
    }


    // 显示菜单
    if (state.viewState.显示菜单) {
        菜单栏(
            显示 = state.viewState.显示菜单,
            onDismissRequest = { state.viewState.显示菜单 = false }
        )
    }
}

@Composable
private fun RowScope.窗口按钮视图(界面模块 : 界面模块 = koinInject()) {
    var 窗口数 by remember { mutableStateOf(0) }
    val ls = 界面模块.窗口列表
    LaunchedEffect(界面模块.窗口列表.size) {
        窗口数 = ls.size.let {
            if (it > 9) 9
            else it
        }
    }
    var 显示窗口列表面板 by remember { mutableStateOf(false) }
    Box(Modifier
        .weight(1f)
        .fillMaxHeight()
        .clickable {
            显示窗口列表面板 = true
        })
    {
        Icon(
            imageVector = MyIconPack.未选中,
            contentDescription = "窗口列表",
            modifier = Modifier.align(Alignment.Center)
        )
        Text(
            text = 窗口数.toString(),
            maxLines = 1,
            style = MaterialTheme.typography.labelMedium,
            color = MaterialTheme.colorScheme.onSurfaceVariant,
            modifier = Modifier.align(Alignment.Center)
        )
    }

    if (显示窗口列表面板) {
        窗口列表面板(
            显示 = 显示窗口列表面板,
            onDismissRequest = { 显示窗口列表面板 = false }
        )
    }
}

@OptIn(ExperimentalMaterial3Api::class)
@Composable
private fun RowScope.标题标签视图(state: 工具栏状态) {
    var 标题 by remember { mutableStateOf("") }

    LaunchedEffect(state.viewState.标题,state.viewState.地址) {
        if (state.viewState.标题.isNotEmpty()) 标题 = state.viewState.标题
        else 标题 = state.viewState.地址
    }

    // 使用2.5倍的权重使其长度为普通按钮的2.5倍
    Box(
        modifier = Modifier
            .weight(2f)
            .clip(MaterialTheme.shapes.medium)
            .padding(horizontal = 5.dp)
            .height(30.dp)
            .background(state.背景次色)
            .fillMaxHeight()
            .clickable2 {
                state.显示输入窗口()
            }.padding(horizontal = 10.dp),
        contentAlignment = Alignment.Center
    ) {
        Text(标题,
            maxLines = 1,
            color = state.内容颜色,
            textAlign = TextAlign.Center,
            style = MaterialTheme.typography.bodyMedium
            )
    }
}

@Composable
private fun RowScope.工具栏按钮(
    state : 工具栏状态,
    icon : ImageVector,
    enable : Boolean,
    clickable : ()-> Unit){

    Box(
        modifier = Modifier
            .weight(1f)
            .fillMaxHeight()
            .then(if (enable) Modifier.clickable {
                clickable()
            } else Modifier)
    ) {
        Icon(
            imageVector = icon,
            contentDescription = "",
            tint = if (enable) state.内容颜色 else state.内容停用色,
            modifier = Modifier.align(Alignment.Center)
        )
    }
}


